/**
 * 性能基准测试脚本
 * Performance Benchmark Script
 */

const http = require('http');
const { performance } = require('perf_hooks');
const { Worker, isMainThread, parentPort, workerData } = require('worker_threads');
const path = require('path');

class PerformanceBenchmark {
  constructor(options = {}) {
    this.baseUrl = options.baseUrl || 'http://localhost:3000';
    this.concurrency = options.concurrency || 10;
    this.duration = options.duration || 30000; // 30秒
    this.warmupTime = options.warmupTime || 5000; // 5秒预热
    this.endpoints = options.endpoints || ['/health'];
    this.results = {
      requests: 0,
      errors: 0,
      responseTimes: [],
      errorTypes: {},
      startTime: 0,
      endTime: 0
    };
  }

  /**
   * 执行HTTP请求
   */
  async makeRequest(endpoint) {
    return new Promise((resolve) => {
      const startTime = performance.now();
      const url = new URL(endpoint, this.baseUrl);
      
      const req = http.get(url, (res) => {
        let data = '';
        
        res.on('data', (chunk) => {
          data += chunk;
        });
        
        res.on('end', () => {
          const responseTime = performance.now() - startTime;
          resolve({
            success: true,
            statusCode: res.statusCode,
            responseTime,
            contentLength: data.length
          });
        });
      });
      
      req.on('error', (error) => {
        const responseTime = performance.now() - startTime;
        resolve({
          success: false,
          error: error.message,
          responseTime
        });
      });
      
      req.setTimeout(10000, () => {
        req.destroy();
        const responseTime = performance.now() - startTime;
        resolve({
          success: false,
          error: 'Request timeout',
          responseTime
        });
      });
    });
  }

  /**
   * 单个工作线程的负载测试
   */
  async runWorkerLoad(workerId, endpoint) {
    const results = {
      requests: 0,
      errors: 0,
      responseTimes: [],
      errorTypes: {}
    };

    const startTime = Date.now();
    const endTime = startTime + this.duration;

    while (Date.now() < endTime) {
      const result = await this.makeRequest(endpoint);
      
      results.requests++;
      results.responseTimes.push(result.responseTime);
      
      if (!result.success) {
        results.errors++;
        const errorType = result.error || 'Unknown error';
        results.errorTypes[errorType] = (results.errorTypes[errorType] || 0) + 1;
      }
      
      // 小延迟以避免过度占用CPU
      await new Promise(resolve => setTimeout(resolve, 1));
    }

    return results;
  }

  /**
   * 运行基准测试
   */
  async runBenchmark() {
    console.log('🚀 开始性能基准测试...');
    console.log(`📊 配置: ${this.concurrency} 并发, ${this.duration/1000}秒持续时间`);
    console.log(`🎯 测试端点: ${this.endpoints.join(', ')}`);
    
    // 预热阶段
    console.log('🔥 预热阶段...');
    await this.warmup();
    
    const allResults = [];
    
    for (const endpoint of this.endpoints) {
      console.log(`\n📈 测试端点: ${endpoint}`);
      
      const endpointResults = await this.testEndpoint(endpoint);
      allResults.push({
        endpoint,
        ...endpointResults
      });
      
      this.printEndpointResults(endpoint, endpointResults);
    }
    
    this.printSummary(allResults);
    return allResults;
  }

  /**
   * 预热测试
   */
  async warmup() {
    const warmupPromises = [];
    const warmupEndTime = Date.now() + this.warmupTime;
    
    while (Date.now() < warmupEndTime) {
      for (const endpoint of this.endpoints) {
        warmupPromises.push(this.makeRequest(endpoint));
      }
      await new Promise(resolve => setTimeout(resolve, 100));
    }
    
    await Promise.all(warmupPromises);
    console.log('✅ 预热完成');
  }

  /**
   * 测试单个端点
   */
  async testEndpoint(endpoint) {
    const startTime = Date.now();
    
    // 使用Worker线程进行并发测试
    const workers = [];
    const workerPromises = [];
    
    for (let i = 0; i < this.concurrency; i++) {
      const workerPromise = this.createWorker(i, endpoint);
      workerPromises.push(workerPromise);
    }
    
    const workerResults = await Promise.all(workerPromises);
    const endTime = Date.now();
    
    // 合并所有工作线程的结果
    const combinedResults = this.combineResults(workerResults);
    combinedResults.totalTime = endTime - startTime;
    combinedResults.rps = combinedResults.requests / (combinedResults.totalTime / 1000);
    
    return combinedResults;
  }

  /**
   * 创建工作线程
   */
  async createWorker(workerId, endpoint) {
    return new Promise((resolve, reject) => {
      const worker = new Worker(__filename, {
        workerData: {
          workerId,
          endpoint,
          baseUrl: this.baseUrl,
          duration: this.duration
        }
      });
      
      worker.on('message', (result) => {
        resolve(result);
      });
      
      worker.on('error', (error) => {
        reject(error);
      });
      
      worker.on('exit', (code) => {
        if (code !== 0) {
          reject(new Error(`Worker stopped with exit code ${code}`));
        }
      });
    });
  }

  /**
   * 合并工作线程结果
   */
  combineResults(workerResults) {
    const combined = {
      requests: 0,
      errors: 0,
      responseTimes: [],
      errorTypes: {}
    };
    
    workerResults.forEach(result => {
      combined.requests += result.requests;
      combined.errors += result.errors;
      combined.responseTimes.push(...result.responseTimes);
      
      Object.keys(result.errorTypes).forEach(errorType => {
        combined.errorTypes[errorType] = (combined.errorTypes[errorType] || 0) + result.errorTypes[errorType];
      });
    });
    
    return combined;
  }

  /**
   * 计算统计信息
   */
  calculateStats(responseTimes) {
    if (responseTimes.length === 0) {
      return { min: 0, max: 0, avg: 0, p50: 0, p95: 0, p99: 0 };
    }
    
    const sorted = responseTimes.sort((a, b) => a - b);
    const len = sorted.length;
    
    return {
      min: sorted[0],
      max: sorted[len - 1],
      avg: sorted.reduce((a, b) => a + b, 0) / len,
      p50: sorted[Math.floor(len * 0.5)],
      p95: sorted[Math.floor(len * 0.95)],
      p99: sorted[Math.floor(len * 0.99)]
    };
  }

  /**
   * 打印端点测试结果
   */
  printEndpointResults(endpoint, results) {
    const stats = this.calculateStats(results.responseTimes);
    const errorRate = (results.errors / results.requests * 100).toFixed(2);
    
    console.log(`\n📊 ${endpoint} 测试结果:`);
    console.log(`   总请求数: ${results.requests}`);
    console.log(`   成功请求: ${results.requests - results.errors}`);
    console.log(`   失败请求: ${results.errors} (${errorRate}%)`);
    console.log(`   RPS: ${results.rps.toFixed(2)}`);
    console.log(`   响应时间统计 (ms):`);
    console.log(`     最小值: ${stats.min.toFixed(2)}`);
    console.log(`     最大值: ${stats.max.toFixed(2)}`);
    console.log(`     平均值: ${stats.avg.toFixed(2)}`);
    console.log(`     P50: ${stats.p50.toFixed(2)}`);
    console.log(`     P95: ${stats.p95.toFixed(2)}`);
    console.log(`     P99: ${stats.p99.toFixed(2)}`);
    
    if (Object.keys(results.errorTypes).length > 0) {
      console.log(`   错误类型:`);
      Object.entries(results.errorTypes).forEach(([type, count]) => {
        console.log(`     ${type}: ${count}`);
      });
    }
  }

  /**
   * 打印总结报告
   */
  printSummary(allResults) {
    console.log('\n' + '='.repeat(60));
    console.log('📋 基准测试总结报告');
    console.log('='.repeat(60));
    
    const totalRequests = allResults.reduce((sum, r) => sum + r.requests, 0);
    const totalErrors = allResults.reduce((sum, r) => sum + r.errors, 0);
    const avgRps = allResults.reduce((sum, r) => sum + r.rps, 0) / allResults.length;
    const overallErrorRate = (totalErrors / totalRequests * 100).toFixed(2);
    
    console.log(`总请求数: ${totalRequests}`);
    console.log(`总错误数: ${totalErrors} (${overallErrorRate}%)`);
    console.log(`平均RPS: ${avgRps.toFixed(2)}`);
    console.log(`测试端点数: ${allResults.length}`);
    console.log(`并发数: ${this.concurrency}`);
    console.log(`测试时长: ${this.duration/1000}秒`);
    
    // 性能评级
    const rating = this.getPerformanceRating(avgRps, parseFloat(overallErrorRate));
    console.log(`\n🏆 性能评级: ${rating.grade} - ${rating.description}`);
    
    console.log('\n💡 建议:');
    rating.suggestions.forEach(suggestion => {
      console.log(`   • ${suggestion}`);
    });
  }

  /**
   * 获取性能评级
   */
  getPerformanceRating(rps, errorRate) {
    if (errorRate > 5) {
      return {
        grade: 'F',
        description: '性能不佳',
        suggestions: [
          '错误率过高，需要检查服务器稳定性',
          '优化错误处理机制',
          '检查资源限制和配置'
        ]
      };
    }
    
    if (rps < 10) {
      return {
        grade: 'D',
        description: '性能较差',
        suggestions: [
          '优化数据库查询',
          '启用缓存机制',
          '检查网络延迟'
        ]
      };
    } else if (rps < 50) {
      return {
        grade: 'C',
        description: '性能一般',
        suggestions: [
          '考虑启用压缩',
          '优化静态资源缓存',
          '检查内存使用情况'
        ]
      };
    } else if (rps < 100) {
      return {
        grade: 'B',
        description: '性能良好',
        suggestions: [
          '可以考虑进一步优化',
          '监控长期性能趋势'
        ]
      };
    } else {
      return {
        grade: 'A',
        description: '性能优秀',
        suggestions: [
          '保持当前配置',
          '定期进行性能监控'
        ]
      };
    }
  }
}

// Worker线程代码
if (!isMainThread) {
  const { workerId, endpoint, baseUrl, duration } = workerData;
  
  const benchmark = new PerformanceBenchmark({ baseUrl });
  
  benchmark.runWorkerLoad(workerId, endpoint)
    .then(result => {
      parentPort.postMessage(result);
    })
    .catch(error => {
      parentPort.postMessage({
        error: error.message,
        requests: 0,
        errors: 1,
        responseTimes: [],
        errorTypes: { [error.message]: 1 }
      });
    });
}

// 主线程代码
if (isMainThread) {
  // 命令行参数解析
  const args = process.argv.slice(2);
  const options = {};
  
  for (let i = 0; i < args.length; i += 2) {
    const key = args[i].replace('--', '');
    const value = args[i + 1];
    
    switch (key) {
      case 'url':
        options.baseUrl = value;
        break;
      case 'concurrency':
        options.concurrency = parseInt(value);
        break;
      case 'duration':
        options.duration = parseInt(value) * 1000;
        break;
      case 'endpoints':
        options.endpoints = value.split(',');
        break;
    }
  }
  
  // 默认配置
  const defaultOptions = {
    baseUrl: 'http://localhost:3000',
    concurrency: 10,
    duration: 30000,
    endpoints: ['/health', '/api/auth/login']
  };
  
  const finalOptions = { ...defaultOptions, ...options };
  
  // 运行基准测试
  const benchmark = new PerformanceBenchmark(finalOptions);
  
  benchmark.runBenchmark()
    .then(() => {
      console.log('\n✅ 基准测试完成');
      process.exit(0);
    })
    .catch(error => {
      console.error('❌ 基准测试失败:', error);
      process.exit(1);
    });
}

module.exports = PerformanceBenchmark;